Skip to content

feat: 优化授权码登录#5914

Merged
KouShenhai merged 1 commit intomasterfrom
dev
Mar 21, 2026
Merged

feat: 优化授权码登录#5914
KouShenhai merged 1 commit intomasterfrom
dev

Conversation

@KouShenhai
Copy link
Owner

@KouShenhai KouShenhai commented Mar 21, 2026

Summary by Sourcery

改进跨认证服务及其支撑组件的登录/授权码流程的认证流与基础设施。

新功能:

  • 为登录页引入基于 UUID 的验证码获取机制,通过新的授权码验证码端点以及在 auth 和 standalone-auth 模块中使用 axios 实现。

改进:

  • 更新登录模板,使用本地静态资源作为背景图片和 JS,调整租户字段命名,并优化错误显示条件。
  • 简化 MinIO 存储集成,将所有 MinIO 相关异常统一为 MinioException,并更新 API 调用方式。
  • 将多个服务和网关切换为使用 framework 转发请求头策略,以改进代理/请求头处理。
  • 扩展安全/请求匹配器配置,开放新的验证码端点和静态 img/js 资源,同时清理已废弃的登录路由。
  • 移除自定义 OAuth2 认证失败处理器,改为使用默认的表单登录行为。
Original summary in English

Summary by Sourcery

Improve the authentication flow and infrastructure for the login/authorization code process across auth services and supporting components.

New Features:

  • Introduce UUID-based captcha retrieval for the login page using a new authorization-code captcha endpoint and axios in both auth and standalone-auth modules.

Enhancements:

  • Update login templates to use local static assets for background images and JS, adjust tenant field naming, and refine error display conditions.
  • Simplify MinIO storage integration by unifying MinIO-related exceptions under MinioException and updating API usage.
  • Switch multiple services and the gateway to use the framework forward-headers strategy for better proxy/header handling.
  • Expand security/request matcher configuration to expose new captcha endpoints and static img/js resources while cleaning up obsolete login routes.
  • Remove the custom OAuth2 authentication failure handler in favor of default form login behavior.

Summary by CodeRabbit

  • New Features

    • Login page now features dynamic captcha generation with client-side UUID handling for enhanced security
  • Bug Fixes

    • Improved authentication error handling and session management
  • Chores

    • Updated HTTP/2 header forwarding strategy across all services
    • Simplified object storage error handling to use unified exception management

@netlify
Copy link

netlify bot commented Mar 21, 2026

Deploy Preview for kcloud-platform-iot ready!

Name Link
🔨 Latest commit f0b8fb9
🔍 Latest deploy log https://app.netlify.com/projects/kcloud-platform-iot/deploys/69be94ac8883be00087c0434
😎 Deploy Preview https://deploy-preview-5914--kcloud-platform-iot.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 21, 2026

Reviewer's Guide

重构登录/授权流程,以使用基于授权码的验证码端点,并在前端通过 UUID 获取验证码;调整静态资源路径和安全匹配规则;简化 MinIO 客户端异常处理;统一服务端转发头策略;移除自定义的 OAuth2 认证失败处理器,改用 Spring Security 默认行为。

授权码验证码获取与登录的时序图

sequenceDiagram
  actor User
  participant Browser
  participant AuthServer

  User->>Browser: Open login page /login
  Browser->>AuthServer: GET /login static resources img js
  AuthServer-->>Browser: HTML CSS JS

  Note over Browser: On page load getCaptcha is executed
  Browser->>Browser: getUuid generate UUID
  Browser->>AuthServer: GET v1/authorization-code/captchas/{uuid}
  AuthServer-->>Browser: captcha image data (base64 or URL)
  Browser->>Browser: Set hidden uuid field and captcha img src

  User->>Browser: Enter tenant_code username password captcha
  User->>Browser: Click login button
  Browser->>AuthServer: POST /login
  activate AuthServer
  AuthServer->>AuthServer: Validate credentials and captcha by uuid
  alt Authentication_success
    AuthServer-->>Browser: 302 redirect to client redirect_uri
    Browser->>User: Show target application
  else Authentication_failure
    AuthServer-->>Browser: 302 redirect /login?error
    Browser->>AuthServer: GET /login?error
    AuthServer-->>Browser: Login page with SPRING_SECURITY_LAST_EXCEPTION message
    Browser->>User: Display error message
  end
  deactivate AuthServer
Loading

更新后的 MinIOStorage 以及移除的 OAuth2AuthenticationFailureHandler 的类图

classDiagram
  class MinIOStorage {
    - MinioProperties minIO
    - FileInfo fileInfo
    + MinioClient getObj()
    + void checkBucket(MinioClient minioClient) throws MinioException
    + void upload(MinioClient minioClient) throws MinioException
    + String getUrl(MinioClient minioClient) throws MinioException
    + void createBucket() throws MinioException
  }

  class OAuth2ResourceServerConfig {
    + SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http, OAuth2AuthorizationService authorizationService, OAuth2TokenGenerator tokenGenerator)
  }

  class OAuth2AuthenticationFailureHandler_removed {
    + void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
  }

  OAuth2ResourceServerConfig ..> MinIOStorage : may use for resource access
  OAuth2ResourceServerConfig ..> OAuth2AuthenticationFailureHandler_removed : previous dependency removed
Loading

文件级变更

Change Details Files
更新登录页面以支持基于授权码的验证码流程(前端通过 UUID 拉取验证码并使用 axios),并改进错误展示与自动填充控制。
  • 在 auth 和 standalone-auth 的登录页面中引入 axios.min.js,并在每个模块下新增一个静态 JS bundle
  • 将背景图片路径从经网关代理的 /api/img 切换为直接使用 /img,通过 Spring 静态资源进行服务
  • 调整错误提示条展示条件:只有在同时存在 error 查询参数和 SPRING_SECURITY_LAST_EXCEPTION 时才显示错误信息(standalone-auth 同时从原来的 model 中 errorMessage 改为使用 session 中的异常)
  • 修改登录表单字段:增加隐藏的 uuid 字段,将 tenant 字段重命名为 tenant_code,并为用户名/密码设置默认值,同时禁用浏览器自动填充
  • 用前端 JS 驱动的验证码替换原有服务器端 /captcha 图片 URL:在浏览器中生成 UUID,写入隐藏字段,并调用 v1/authorization-code/captchas/{uuid} 获取并设置验证码图片 src;在页面加载时初始化验证码
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/static/js/axios.min.js
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/static/js/axios.min.js
对新的验证码端点和静态资源的安全及路由配置进行对齐,同时简化通过网关的登录路由。
  • 在 standalone-auth 中,将允许匿名的 GET 路径改为 /v1/username-password/captchas/{uuid}/v1/authorization-code/captchas/{uuid},并显式暴露 /img/**/js/**
  • 在 auth 中,确保 /img/**/js/** 被允许匿名访问,并从 security matcher 中移除显式的 /login 映射(登录仍然由 Spring Security/formLogin 处理)
  • 在 gateway 配置中,从请求匹配器中移除 /api/login,不再在网关层对登录端点进行暴露
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml
laokou-cloud/laokou-gateway/src/main/resources/application.yml
统一各服务的 server.forward-headers-strategy 配置,改为使用 Spring framework 的处理方式而不是 native。
  • 将 auth、standalone-auth、gateway、admin、standalone-admin、generator、logstash、network、oss、report 等服务中的 server.forward-headers-strategynative 修改为 framework,以更好地支持代理/负载均衡器相关请求头
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml
laokou-cloud/laokou-gateway/src/main/resources/application.yml
laokou-service/laokou-admin/laokou-admin-start/src/main/resources/application.yml
laokou-service/laokou-generator/laokou-generator-start/src/main/resources/application.yml
laokou-service/laokou-logstash/laokou-logstash-start/src/main/resources/application.yml
laokou-service/laokou-network/laokou-network-start/src/main/resources/application.yml
laokou-service/laokou-oss/laokou-oss-start/src/main/resources/application.yml
laokou-service/laokou-report/laokou-report-start/src/main/resources/application.yml
laokou-service/laokou-standalone/laokou-standalone-admin/laokou-standalone-admin-start/src/main/resources/application.yml
简化 MinIO 存储模板,以使用 MinioException 和更新后的 API 类型。
  • MinIOStoragecheckBucketuploadgetUrlcreateBucket 方法里多个受检异常折叠为统一的 MinioException,以简化方法签名
  • putObject 的流大小参数从 -1 改为 -1L,以匹配期望的 long 类型
  • GetPresignedObjectUrlArgs.method 从 MinIO 的 Method 枚举切换为 Http.Method.GET
laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java
依赖 Spring Security 默认的登录失败处理逻辑,而不是自定义的 OAuth2AuthenticationFailureHandler
  • 完全移除自定义的 OAuth2AuthenticationFailureHandler
  • formLogin 配置中删除显式的 .failureHandler(...),让 Spring 使用默认行为
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthenticationFailureHandler.java

可能关联的需求/问题

  • #:该 PR 优化并补全授权码登录与验证码的交互流程,是对“支持授权码登录”这一需求的具体实现与完善。

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the
    pull request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Original review guide in English

Reviewer's Guide

Refactors the login/authorization flow to use an authorization-code captcha endpoint with UUID-based captcha retrieval on the front-end, adjusts static asset paths and security matchers, simplifies MinIO client exception handling, standardizes server forward-headers strategy, and removes the custom OAuth2 authentication failure handler in favor of the default behavior.

Sequence diagram for authorization-code captcha retrieval and login

sequenceDiagram
  actor User
  participant Browser
  participant AuthServer

  User->>Browser: Open login page /login
  Browser->>AuthServer: GET /login static resources img js
  AuthServer-->>Browser: HTML CSS JS

  Note over Browser: On page load getCaptcha is executed
  Browser->>Browser: getUuid generate UUID
  Browser->>AuthServer: GET v1/authorization-code/captchas/{uuid}
  AuthServer-->>Browser: captcha image data (base64 or URL)
  Browser->>Browser: Set hidden uuid field and captcha img src

  User->>Browser: Enter tenant_code username password captcha
  User->>Browser: Click login button
  Browser->>AuthServer: POST /login
  activate AuthServer
  AuthServer->>AuthServer: Validate credentials and captcha by uuid
  alt Authentication_success
    AuthServer-->>Browser: 302 redirect to client redirect_uri
    Browser->>User: Show target application
  else Authentication_failure
    AuthServer-->>Browser: 302 redirect /login?error
    Browser->>AuthServer: GET /login?error
    AuthServer-->>Browser: Login page with SPRING_SECURITY_LAST_EXCEPTION message
    Browser->>User: Display error message
  end
  deactivate AuthServer
Loading

Class diagram for updated MinIOStorage and removed OAuth2AuthenticationFailureHandler

classDiagram
  class MinIOStorage {
    - MinioProperties minIO
    - FileInfo fileInfo
    + MinioClient getObj()
    + void checkBucket(MinioClient minioClient) throws MinioException
    + void upload(MinioClient minioClient) throws MinioException
    + String getUrl(MinioClient minioClient) throws MinioException
    + void createBucket() throws MinioException
  }

  class OAuth2ResourceServerConfig {
    + SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http, OAuth2AuthorizationService authorizationService, OAuth2TokenGenerator tokenGenerator)
  }

  class OAuth2AuthenticationFailureHandler_removed {
    + void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
  }

  OAuth2ResourceServerConfig ..> MinIOStorage : may use for resource access
  OAuth2ResourceServerConfig ..> OAuth2AuthenticationFailureHandler_removed : previous dependency removed
Loading

File-Level Changes

Change Details Files
Update login pages to support authorization-code captcha flow with UUID-based captcha retrieval and axios, plus improved error display and autocomplete control.
  • Include axios.min.js on auth and standalone-auth login pages and add a static JS bundle under each module
  • Switch background image path from proxied /api/img to direct /img to serve via Spring static resources
  • Change error banner condition to require both error query param and SPRING_SECURITY_LAST_EXCEPTION before showing the message (standalone-auth also changes from model errorMessage to session exception)
  • Modify login form fields to include hidden uuid, rename tenant to tenant_code, and prefill username/password defaults while disabling browser autocomplete
  • Replace server-side /captcha image URL with JS-driven captcha: generate UUID in browser, store it in hidden field, and call v1/authorization-code/captchas/{uuid} to obtain and set the captcha image src; initialize captcha on page load
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/static/js/axios.min.js
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/static/js/axios.min.js
Align security and routing configuration for new captcha endpoints and static resources while simplifying login routing through the gateway.
  • In standalone-auth, change permitted GET paths to use /v1/username-password/captchas/{uuid} and /v1/authorization-code/captchas/{uuid} and explicitly expose /img/** and /js/
  • In auth, ensure /img/ and /js/** are permitted and remove explicit /login mapping from the security matcher (login remains handled by Spring Security/formLogin)
  • In gateway config, remove /api/login from the request matcher to stop gateway-level login endpoint exposure
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml
laokou-cloud/laokou-gateway/src/main/resources/application.yml
Standardize server forward-headers strategy across services to use Spring framework handling instead of native.
  • Change server.forward-headers-strategy from native to framework for auth, standalone-auth, gateway, admin, standalone-admin, generator, logstash, network, oss, and report services to better support proxy/load balancer headers
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml
laokou-cloud/laokou-gateway/src/main/resources/application.yml
laokou-service/laokou-admin/laokou-admin-start/src/main/resources/application.yml
laokou-service/laokou-generator/laokou-generator-start/src/main/resources/application.yml
laokou-service/laokou-logstash/laokou-logstash-start/src/main/resources/application.yml
laokou-service/laokou-network/laokou-network-start/src/main/resources/application.yml
laokou-service/laokou-oss/laokou-oss-start/src/main/resources/application.yml
laokou-service/laokou-report/laokou-report-start/src/main/resources/application.yml
laokou-service/laokou-standalone/laokou-standalone-admin/laokou-standalone-admin-start/src/main/resources/application.yml
Simplify MinIO storage template to use MinioException and updated API types.
  • Collapse multiple checked exceptions into MinioException in MinIOStorage methods checkBucket, upload, getUrl, and createBucket for cleaner signatures
  • Update putObject stream size argument to use -1L instead of -1 to match expected long type
  • Switch GetPresignedObjectUrlArgs.method from MinIO Method enum to Http.Method.GET
laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java
Rely on Spring Security default login failure handling instead of a custom OAuth2AuthenticationFailureHandler.
  • Remove the custom OAuth2AuthenticationFailureHandler class entirely
  • Delete the explicit .failureHandler(...) configuration from formLogin to let Spring use default behavior
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthenticationFailureHandler.java

Possibly linked issues

  • #: 该PR优化并补全授权码登录与验证码交互,正是“支持授权码登录”需求的实现与完善。

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@KouShenhai KouShenhai merged commit d3b57af into master Mar 21, 2026
12 of 16 checks passed
@coderabbitai
Copy link

coderabbitai bot commented Mar 21, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f038edb1-248f-41f0-abc7-adcb3449008f

📥 Commits

Reviewing files that changed from the base of the PR and between b707205 and f0b8fb9.

⛔ Files ignored due to path filters (2)
  • laokou-service/laokou-auth/laokou-auth-start/src/main/resources/static/js/axios.min.js is excluded by !**/*.min.js
  • laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/static/js/axios.min.js is excluded by !**/*.min.js
📒 Files selected for processing (15)
  • laokou-cloud/laokou-gateway/src/main/resources/application.yml
  • laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java
  • laokou-service/laokou-admin/laokou-admin-start/src/main/resources/application.yml
  • laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthenticationFailureHandler.java
  • laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java
  • laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml
  • laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html
  • laokou-service/laokou-generator/laokou-generator-start/src/main/resources/application.yml
  • laokou-service/laokou-logstash/laokou-logstash-start/src/main/resources/application.yml
  • laokou-service/laokou-network/laokou-network-start/src/main/resources/application.yml
  • laokou-service/laokou-oss/laokou-oss-start/src/main/resources/application.yml
  • laokou-service/laokou-report/laokou-report-start/src/main/resources/application.yml
  • laokou-service/laokou-standalone/laokou-standalone-admin/laokou-standalone-admin-start/src/main/resources/application.yml
  • laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml
  • laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html

Walkthrough

This pull request updates the HTTP/2 forward headers strategy across multiple services from native to framework, simplifies MinIO exception handling to use a unified exception type, removes OAuth2 authentication failure handling logic, and refactors the login template with client-side UUID generation and axios-based captcha fetching instead of server-rendered URLs.

Changes

Cohort / File(s) Summary
HTTP/2 Forward Headers Configuration
laokou-cloud/laokou-gateway/...application.yml, laokou-service/laokou-admin/...application.yml, laokou-service/laokou-auth/...application.yml, laokou-service/laokou-generator/...application.yml, laokou-service/laokou-logstash/...application.yml, laokou-service/laokou-network/...application.yml, laokou-service/laokou-oss/...application.yml, laokou-service/laokou-report/...application.yml, laokou-service/laokou-standalone/...application.yml
Changed server.http2.forward-headers-strategy (or server.forward-headers-strategy) from native to framework across all application configuration files, affecting how forwarded headers are processed.
MinIO Exception Handling
laokou-common/laokou-common-oss/.../MinIOStorage.java
Consolidated exception handling by replacing multiple MinIO-specific and cryptography exceptions with single MinioException in checkBucket(), upload(), getUrl(), and createBucket() methods. Also adjusted Http.Method import path and changed upload stream size parameter from -1 (int) to -1L (long).
OAuth2 Authentication Failure Handler
laokou-service/laokou-auth/.../OAuth2AuthenticationFailureHandler.java, laokou-service/laokou-auth/.../OAuth2ResourceServerConfig.java
Removed OAuth2AuthenticationFailureHandler class entirely and removed its commented-out reference in security configuration, eliminating custom error message storage logic during authentication failures.
Security Request Matcher Patterns
laokou-cloud/laokou-gateway/...application.yml, laokou-service/laokou-auth/...application.yml, laokou-service/laokou-standalone/laokou-standalone-auth/...application.yml
Modified ignore patterns: removed /api/login=laokou-gateway from gateway patterns, replaced /v1/captchas/{uuid} with /v1/username-password/captchas/{uuid} and /v1/authorization-code/captchas/{uuid} in auth service, and added /img/** and /js/** static asset patterns.
Login Template with Captcha Refactoring
laokou-service/laokou-auth/...login.html, laokou-service/laokou-standalone/laokou-standalone-auth/...login.html
Added Axios library dependency and JavaScript functions (getUuid(), getCaptcha()) for client-side UUID generation and axios-based captcha fetching. Replaced server-rendered captcha URL with dynamic image element. Changed form to use hidden UUID field instead of visible tenant field, prefilled credentials with defaults, disabled autocomplete, and updated background image from absolute /api/img/ to relative img/ path. Modified error display to read from Spring Security session exception.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

Review effort 3/5, Possible security concern

Poem

🐰 Headers now flow through framework's way,
MinIO errors simplified to play,
Login captcha dances with UUID grace,
Axios fetches at a swifter pace,
Auth handlers vanish, new patterns stay! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.16.4)
laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can approve the review once all CodeRabbit's comments are resolved.

Enable the reviews.request_changes_workflow setting to automatically approve the review once all CodeRabbit's comments are resolved.

@qodo-code-review
Copy link

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Optimize authorization code login with Axios integration and configuration standardization

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Refactored authorization code login flow with improved frontend implementation using Axios HTTP
  client library
• Updated login forms in both standalone and standard auth services with dynamic captcha loading via
  getCaptcha() function
• Refactored form fields: replaced tenant with tenant_code, added hidden uuid field for
  captcha request tracking
• Added default credentials for testing (tenant_code: laokouyun, username: admin, password:
  admin123)
• Changed background image URLs from absolute paths to relative paths for better portability
• Simplified MinIO exception handling by consolidating multiple specific exceptions into single
  MinioException parent class
• Updated import statements in MinIO storage to use io.minio.Http instead of
  io.minio.http.Method
• Standardized forward-headers-strategy configuration from native to framework across all
  services (gateway, auth, logstash, OSS, generator, report, admin, network)
• Added route permissions for static resources (/img/**, /js/**) in auth service configuration
• Removed OAuth2 authentication failure handler class as part of login flow optimization
Diagram
flowchart LR
  A["Login Form<br/>HTML"] -->|"Axios HTTP<br/>Requests"| B["Captcha<br/>Endpoint"]
  A -->|"Form Fields<br/>tenant_code, uuid"| C["Backend<br/>Auth Service"]
  D["MinIO Storage<br/>Exception Handling"] -->|"Simplified<br/>to MinioException"| E["Error Processing"]
  F["All Services<br/>Configuration"] -->|"forward-headers-strategy<br/>native → framework"| G["Gateway &<br/>Services"]
  C -->|"Static Resources<br/>/img/**, /js/**"| H["Frontend<br/>Assets"]
Loading

Grey Divider

File Changes

1. laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java ✨ Enhancement +8/-24

Simplify MinIO exception handling and update imports

• Simplified exception handling by replacing multiple specific MinIO exceptions with a single
 MinioException parent class
• Updated import statements to use io.minio.Http instead of io.minio.http.Method
• Changed method signature for Method.GET to Http.Method.GET
• Fixed type casting from -1 to -1L for long parameter

laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java


2. laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/static/js/axios.min.js Dependencies +5/-0

Add Axios HTTP client library for frontend requests

• Added minified Axios v1.13.6 JavaScript library for HTTP client functionality
• Includes full implementation of HTTP request/response handling with interceptors
• Supports promise-based API and various HTTP methods

laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/static/js/axios.min.js


3. laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html ✨ Enhancement +35/-10

Refactor login form with Axios and dynamic captcha

• Added Axios script import for HTTP requests
• Changed background image URL from absolute path /api/img/... to relative path img/...
• Refactored form fields: replaced tenant with tenant_code, added hidden uuid field
• Added default values for tenant_code (laokouyun), username (admin), and password (admin123)
• Implemented dynamic captcha loading via getCaptcha() function using Axios
• Added getUuid() function to generate unique identifiers for captcha requests
• Updated captcha image element to use id="captcha-img" with onclick handler

laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html


View more (14)
4. laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html ✨ Enhancement +34/-9

Refactor login form with Axios and dynamic captcha

• Added Axios script import for HTTP requests
• Changed background image URL from absolute path /api/img/... to relative path img/...
• Refactored form fields: replaced tenant with tenant_code, added hidden uuid field
• Added default values for tenant_code (laokouyun), username (admin), and password (admin123)
• Implemented dynamic captcha loading via getCaptcha() function using Axios
• Added getUuid() function to generate unique identifiers for captcha requests
• Updated captcha image element to use id="captcha-img" with onclick handler

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html


5. laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml ⚙️ Configuration changes +5/-2

Update server configuration and route permissions

• Changed forward-headers-strategy from native to framework
• Updated captcha endpoint path from /v1/captchas/{uuid} to
 /v1/username-password/captchas/{uuid} and added /v1/authorization-code/captchas/{uuid}
• Added new route permissions for /img/** and /js/** static resources

laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/application.yml


6. laokou-cloud/laokou-gateway/src/main/resources/application.yml ⚙️ Configuration changes +1/-2

Update gateway forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-cloud/laokou-gateway/src/main/resources/application.yml


7. laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml ⚙️ Configuration changes +2/-2

Update auth service configuration

• Changed forward-headers-strategy from native to framework
• Added /js/** route permission for static JavaScript resources
• Removed /login route permission

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml


8. laokou-service/laokou-logstash/laokou-logstash-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update logstash forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-logstash/laokou-logstash-start/src/main/resources/application.yml


9. laokou-service/laokou-oss/laokou-oss-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update OSS service forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-oss/laokou-oss-start/src/main/resources/application.yml


10. laokou-service/laokou-generator/laokou-generator-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update generator service forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-generator/laokou-generator-start/src/main/resources/application.yml


11. laokou-service/laokou-report/laokou-report-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update report service forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-report/laokou-report-start/src/main/resources/application.yml


12. laokou-service/laokou-standalone/laokou-standalone-admin/laokou-standalone-admin-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update standalone admin forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-standalone/laokou-standalone-admin/laokou-standalone-admin-start/src/main/resources/application.yml


13. laokou-service/laokou-admin/laokou-admin-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update admin service forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-admin/laokou-admin-start/src/main/resources/application.yml


14. laokou-service/laokou-network/laokou-network-start/src/main/resources/application.yml ⚙️ Configuration changes +1/-1

Update network service forward headers strategy

• Changed forward-headers-strategy from native to framework

laokou-service/laokou-network/laokou-network-start/src/main/resources/application.yml


15. laokou-service/laokou-auth/laokou-auth-start/src/main/resources/static/js/axios.min.js Dependencies +5/-0

Add Axios HTTP client library for authorization code login

• Added minified Axios v1.13.6 library with complete HTTP client functionality
• Includes support for XMLHttpRequest, Fetch API, and Node.js adapters
• Provides request/response interceptors, cancellation tokens, and error handling
• Contains regenerator-runtime for async/await support in older environments

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/static/js/axios.min.js


16. laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthenticationFailureHandler.java Additional files +0/-45

...

laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthenticationFailureHandler.java


17. laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java Additional files +0/-1

...

laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 21, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. Login blocked by gateway 🐞 Bug ✓ Correctness
Description
网关移除了 /api/login 的放行规则后,AuthFilter 会对未带 Authorization 的登录页请求直接返回 401,导致授权码登录页不可访问。由于 auth 服务
context-path 为 /api 且 LoginController 映射 /login,登录页实际路径为 /api/login。
Code

laokou-cloud/laokou-gateway/src/main/resources/application.yml[202]

-      - /api/login=laokou-gateway
Evidence
网关 AuthFilter 在请求不匹配 ignore-patterns 时要求必须携带 Authorization,否则返回 UNAUTHORIZED(401)。当前网关
ignore-patterns 列表中已不包含 /api/login,因此访问 /api/login 将无法命中放行路径。与此同时 auth 服务配置了 context-path=/api,且
LoginController 映射 /login,合成后的登录页路径为 /api/login。

laokou-cloud/laokou-gateway/src/main/java/org/laokou/gateway/filter/AuthFilter.java[64-86]
laokou-cloud/laokou-gateway/src/main/resources/application.yml[190-207]
laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml[30-55]
laokou-service/laokou-auth/laokou-auth-adapter/src/main/java/org/laokou/auth/web/LoginController.java[24-38]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Gateway 的 `request-matcher.ignore-patterns.GET` 中移除了 `/api/login`,而 `AuthFilter` 对未命中放行列表且缺少 `Authorization` 的请求会直接返回 401,导致登录页(`/api/login`)无法访问。

### Issue Context
- auth 服务 `server.servlet.context-path=/api`,`GET /login` 实际对外为 `/api/login`。
- 登录页还会加载静态资源(例如 `/api/js/**`, `/api/img/**`),如通过网关访问也应同步放行。

### Fix Focus Areas
- laokou-cloud/laokou-gateway/src/main/resources/application.yml[190-207]
- laokou-cloud/laokou-gateway/src/main/java/org/laokou/gateway/filter/AuthFilter.java[64-86]
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml[30-55]
- laokou-service/laokou-auth/laokou-auth-adapter/src/main/java/org/laokou/auth/web/LoginController.java[24-38]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Hardcoded admin credentials 🐞 Bug ⛨ Security
Description
两个 login.html 模板将 tenant_code/username/password 预填为
laokouyun/admin/admin123,任何未认证访问者都能直接看到并一键尝试该组合,存在明显账号安全风险。
Code

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[R108-121]

+			<input id="uuid" name="uuid" type="text" autocomplete="new-password" hidden="hidden" placeholder="请输入唯一标识" required/>
		</div>

		<div class="form-item row" style="width: 100%;">
-			<input id="username" name="username" type="text" placeholder="请输入用户名" required/>
+			<input id="tenant_code" name="tenant_code" autocomplete="new-password" value="laokouyun" type="text" placeholder="请输入租户编号" required autofocus/>
		</div>

		<div class="form-item row" style="width: 100%;">
-			<input id="password" name="password" type="password" placeholder="请输入密码" required/>
+			<input id="username" name="username" type="text" autocomplete="new-password" value="admin" placeholder="请输入用户名" required/>
+		</div>
+
+		<div class="form-item row" style="width: 100%;">
+			<input id="password" name="password" type="password" autocomplete="new-password" value="admin123" placeholder="请输入密码" required/>
		</div>
Evidence
登录页表单输入框直接包含 value="admin" 和 value="admin123"(以及租户编码默认值),这些内容会被下发到浏览器端并暴露给所有访问登录页的用户。该问题在 auth 与
standalone-auth 两套模板中同时存在。

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[107-121]
laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html[107-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
登录页模板硬编码并预填了 `tenant_code` / `username` / `password`(`laokouyun` / `admin` / `admin123`)。这会把“默认凭据”暴露给所有访问者,并显著降低账号安全性。

### Issue Context
这是服务端渲染模板(Thymeleaf),任何未认证访问者都可查看页面源代码或直接看到输入框中的默认值。

### Fix Focus Areas
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[111-121]
- laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html[111-121]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Captcha not validated server-side 🐞 Bug ⛨ Security
Description
登录页强制填写 uuid/captcha 并从 /v1/authorization-code/captchas/{uuid} 获取验证码,但当前 formLogin 认证链路使用默认
DaoAuthenticationProvider,未看到对 uuid/captcha 的服务端校验,验证码形同虚设且可被直接绕过。
Code

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[R123-152]

		<div class="form-item">
			<div class="row">
-				<input id="captcha" name="captcha" type="text" placeholder="请输入验证码" required/>
-				<img class="captcha" th:src="@{/captcha}" alt="captcha"
-					 onclick="this.src='/captcha?ts='+Date.now()"/>
+				<input id="captcha" name="captcha" autocomplete="new-password" type="text" placeholder="请输入验证码" required/>
+				<img id="captcha-img" class="captcha" alt="验证码" onclick="getCaptcha()"/>
			</div>
		</div>

		<button class="btn" type="submit">登&nbsp;&nbsp;录</button>
	</form>
</div>
+<script>
+	function getUuid() {
+		if (window.crypto && crypto.randomUUID) {
+			return crypto.randomUUID();
+		}
+		return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+			const r = Math.random() * 16 | 0;
+			const v = c === 'x' ? r : (r & 0x3 | 0x8);
+			return v.toString(16);
+		});
+	}
+	function getCaptcha() {
+		const uuid = getUuid()
+		document.getElementById("uuid").value = uuid
+		axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
+			document.getElementById("captcha-img").src = res.data.data
+		})
+	}
+	getCaptcha()
+</script>
Evidence
模板中新增了 uuid(hidden)和 captcha(required)字段,并在页面加载/点击时通过 axios 调用授权码验证码接口获取图片。该接口会把验证码文本写入 Redis
并返回 base64 图片数据;但资源服务器安全配置仅启用标准的 .formLogin(),且认证提供者为 DaoAuthenticationProvider,这条标准链路只验证
username/password,不会校验自定义的 uuid/captcha 参数。

laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[107-152]
laokou-service/laokou-auth/laokou-auth-app/src/main/java/org/laokou/auth/command/query/CaptchaGetQryExe.java[40-51]
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java[49-72]
laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthorizationServerConfig.java[176-186]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
登录页引入了 `uuid`/`captcha` 并要求用户填写,但当前 Spring Security 的 formLogin 认证链路未实现对这些参数的服务端校验,导致验证码只存在于前端交互层面,攻击者可直接 POST `/login` 绕过。

### Issue Context
- GET `/v1/authorization-code/captchas/{uuid}` 会生成验证码并写入 Redis(key 由控制器使用 `RedisKeyUtils.getAuthorizationCodeAuthCaptchaKey(uuid)` 生成),并返回 base64 图片。
- 但 formLogin 使用默认认证流程(DaoAuthenticationProvider),默认只校验 username/password。

### Fix Focus Areas
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[107-152]
- laokou-service/laokou-auth/laokou-auth-app/src/main/java/org/laokou/auth/command/query/CaptchaGetQryExe.java[40-51]
- laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java[49-72]
- laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthorizationServerConfig.java[176-186]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了两个问题,并给出了一些整体性的反馈:

  • 登录表单现在对 tenant_code/username/password 使用了硬编码的默认值,这在非演示环境中存在风险;建议移除这些默认值,或者只在开发/特定 profile 模板中启用。
  • 隐藏的 uuid 输入框被标记为 required,但只会通过 getCaptcha() 来赋值,如果 JS 或验证码请求失败,表单可能会变得不可用;建议取消必填限制,或在验证码请求失败时添加错误处理/降级方案。
  • MinIOStorage 中,方法签名被收紧为只抛出 MinioException,但 MinIO 客户端 API 实际上还可能抛出其他受检异常(例如 IOExceptionNoSuchAlgorithmException);请确保这些异常要么仍然在方法签名中声明,要么被正确包装/处理,以保持编译和错误处理逻辑的一致性。
给 AI Agents 的提示
Please address the comments from this code review:

## Overall Comments
- The login form now hardcodes default tenant_code/username/password values, which is risky for non-demo environments; consider removing these defaults or gating them behind a dev/profile-specific template.
- The hidden `uuid` input is marked `required` but is only populated by `getCaptcha()`, so if JS or the captcha request fails the form may become unusable; consider making it non-required or adding error handling/fallback when the captcha call fails.
- In `MinIOStorage`, the method signatures were narrowed to only throw `MinioException` while the MinIO client APIs can also throw other checked exceptions (e.g. `IOException`, `NoSuchAlgorithmException`); ensure these are either still declared or properly wrapped/handled to keep compilation and error handling consistent.

## Individual Comments

### Comment 1
<location path="laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html" line_range="144-151" />
<code_context>
+			return v.toString(16);
+		});
+	}
+	function getCaptcha() {
+		const uuid = getUuid()
+		document.getElementById("uuid").value = uuid
+		axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
+			document.getElementById("captcha-img").src = res.data.data
+		})
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Captcha loading has no error handling, which can degrade the login experience.

If the captcha request fails (network/server issue), the image stays blank and the user can’t proceed or recover. Add error handling (e.g. a `.catch(...)` to display an error and/or trigger a retry) and consider regenerating the `uuid` so the form isn’t stuck on a failed captcha.

```suggestion
	function getCaptcha() {
		const uuid = getUuid();
		const uuidInput = document.getElementById("uuid");
		const captchaImg = document.getElementById("captcha-img");

		// 如果关键元素不存在,直接返回避免报错
		if (!uuidInput || !captchaImg) {
			console.error("Captcha elements not found on the page.");
			return;
		}

		uuidInput.value = uuid;
		captchaImg.alt = "验证码加载中...";

		axios
			.get("v1/authorization-code/captchas/" + uuid)
			.then(res => {
				captchaImg.src = res.data.data;
				captchaImg.alt = "看不清?点击刷新验证码";
			})
			.catch(err => {
				console.error("Failed to load captcha.", err);
				// 清空图片,避免展示旧的或损坏的图片
				captchaImg.removeAttribute("src");
				captchaImg.alt = "验证码加载失败,点击重试";
				// 简单用户提示;如果项目有全局消息组件,可替换为全局提示
				alert("验证码加载失败,请检查网络后点击验证码重试。");
			});
	}

	const captchaImg = document.getElementById("captcha-img");
	if (captchaImg) {
		// 允许用户点击验证码重新获取,避免因为一次请求失败而卡死
		captchaImg.addEventListener("click", getCaptcha);
	}

	getCaptcha();
```
</issue_to_address>

### Comment 2
<location path="laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java" line_range="77-81" />
<code_context>
-	protected String getUrl(MinioClient minioClient) throws ServerException, InsufficientDataException,
-			ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
-			InvalidResponseException, XmlParserException, InternalException {
+	protected String getUrl(MinioClient minioClient) throws MinioException {
 		GetPresignedObjectUrlArgs objectUrlArgs = GetPresignedObjectUrlArgs.builder()
 			.bucket(this.minIO.getBucketName())
 			.object(fileInfo.name())
-			.method(Method.GET)
+			.method(Http.Method.GET)
 			.expiry(5, TimeUnit.DAYS)
 			.build();
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `Http.Method.GET` with MinIO’s `GetPresignedObjectUrlArgs` looks inconsistent and may not compile.

This previously used MinIO’s `io.minio.http.Method.GET`, but now passes `Http.Method.GET` into `.method(...)`. Unless `Http.Method` is the same type as `io.minio.http.Method`, this will fail to compile or be rejected by the builder. Please either keep using MinIO’s `Method` enum or add an explicit conversion from `Http.Method` to the type expected by `GetPresignedObjectUrlArgs.builder().method(...)`.
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的 Review。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • The login form now hardcodes default tenant_code/username/password values, which is risky for non-demo environments; consider removing these defaults or gating them behind a dev/profile-specific template.
  • The hidden uuid input is marked required but is only populated by getCaptcha(), so if JS or the captcha request fails the form may become unusable; consider making it non-required or adding error handling/fallback when the captcha call fails.
  • In MinIOStorage, the method signatures were narrowed to only throw MinioException while the MinIO client APIs can also throw other checked exceptions (e.g. IOException, NoSuchAlgorithmException); ensure these are either still declared or properly wrapped/handled to keep compilation and error handling consistent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The login form now hardcodes default tenant_code/username/password values, which is risky for non-demo environments; consider removing these defaults or gating them behind a dev/profile-specific template.
- The hidden `uuid` input is marked `required` but is only populated by `getCaptcha()`, so if JS or the captcha request fails the form may become unusable; consider making it non-required or adding error handling/fallback when the captcha call fails.
- In `MinIOStorage`, the method signatures were narrowed to only throw `MinioException` while the MinIO client APIs can also throw other checked exceptions (e.g. `IOException`, `NoSuchAlgorithmException`); ensure these are either still declared or properly wrapped/handled to keep compilation and error handling consistent.

## Individual Comments

### Comment 1
<location path="laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html" line_range="144-151" />
<code_context>
+			return v.toString(16);
+		});
+	}
+	function getCaptcha() {
+		const uuid = getUuid()
+		document.getElementById("uuid").value = uuid
+		axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
+			document.getElementById("captcha-img").src = res.data.data
+		})
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Captcha loading has no error handling, which can degrade the login experience.

If the captcha request fails (network/server issue), the image stays blank and the user can’t proceed or recover. Add error handling (e.g. a `.catch(...)` to display an error and/or trigger a retry) and consider regenerating the `uuid` so the form isn’t stuck on a failed captcha.

```suggestion
	function getCaptcha() {
		const uuid = getUuid();
		const uuidInput = document.getElementById("uuid");
		const captchaImg = document.getElementById("captcha-img");

		// 如果关键元素不存在,直接返回避免报错
		if (!uuidInput || !captchaImg) {
			console.error("Captcha elements not found on the page.");
			return;
		}

		uuidInput.value = uuid;
		captchaImg.alt = "验证码加载中...";

		axios
			.get("v1/authorization-code/captchas/" + uuid)
			.then(res => {
				captchaImg.src = res.data.data;
				captchaImg.alt = "看不清?点击刷新验证码";
			})
			.catch(err => {
				console.error("Failed to load captcha.", err);
				// 清空图片,避免展示旧的或损坏的图片
				captchaImg.removeAttribute("src");
				captchaImg.alt = "验证码加载失败,点击重试";
				// 简单用户提示;如果项目有全局消息组件,可替换为全局提示
				alert("验证码加载失败,请检查网络后点击验证码重试。");
			});
	}

	const captchaImg = document.getElementById("captcha-img");
	if (captchaImg) {
		// 允许用户点击验证码重新获取,避免因为一次请求失败而卡死
		captchaImg.addEventListener("click", getCaptcha);
	}

	getCaptcha();
```
</issue_to_address>

### Comment 2
<location path="laokou-common/laokou-common-oss/src/main/java/org/laokou/common/oss/template/MinIOStorage.java" line_range="77-81" />
<code_context>
-	protected String getUrl(MinioClient minioClient) throws ServerException, InsufficientDataException,
-			ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
-			InvalidResponseException, XmlParserException, InternalException {
+	protected String getUrl(MinioClient minioClient) throws MinioException {
 		GetPresignedObjectUrlArgs objectUrlArgs = GetPresignedObjectUrlArgs.builder()
 			.bucket(this.minIO.getBucketName())
 			.object(fileInfo.name())
-			.method(Method.GET)
+			.method(Http.Method.GET)
 			.expiry(5, TimeUnit.DAYS)
 			.build();
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `Http.Method.GET` with MinIO’s `GetPresignedObjectUrlArgs` looks inconsistent and may not compile.

This previously used MinIO’s `io.minio.http.Method.GET`, but now passes `Http.Method.GET` into `.method(...)`. Unless `Http.Method` is the same type as `io.minio.http.Method`, this will fail to compile or be rejected by the builder. Please either keep using MinIO’s `Method` enum or add an explicit conversion from `Http.Method` to the type expected by `GetPresignedObjectUrlArgs.builder().method(...)`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +144 to +151
function getCaptcha() {
const uuid = getUuid()
document.getElementById("uuid").value = uuid
axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
document.getElementById("captcha-img").src = res.data.data
})
}
getCaptcha()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): 验证码加载过程没有错误处理,会影响登录体验。

如果验证码请求失败(网络/服务端问题),图片会保持空白,用户既无法继续也无法恢复。建议添加错误处理(例如使用 .catch(...) 显示错误并/或触发重试),并考虑在验证码获取失败时重新生成 uuid,避免表单卡在一次失败的验证码请求上。

Suggested change
function getCaptcha() {
const uuid = getUuid()
document.getElementById("uuid").value = uuid
axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
document.getElementById("captcha-img").src = res.data.data
})
}
getCaptcha()
function getCaptcha() {
const uuid = getUuid();
const uuidInput = document.getElementById("uuid");
const captchaImg = document.getElementById("captcha-img");
// 如果关键元素不存在,直接返回避免报错
if (!uuidInput || !captchaImg) {
console.error("Captcha elements not found on the page.");
return;
}
uuidInput.value = uuid;
captchaImg.alt = "验证码加载中...";
axios
.get("v1/authorization-code/captchas/" + uuid)
.then(res => {
captchaImg.src = res.data.data;
captchaImg.alt = "看不清?点击刷新验证码";
})
.catch(err => {
console.error("Failed to load captcha.", err);
// 清空图片,避免展示旧的或损坏的图片
captchaImg.removeAttribute("src");
captchaImg.alt = "验证码加载失败,点击重试";
// 简单用户提示;如果项目有全局消息组件,可替换为全局提示
alert("验证码加载失败,请检查网络后点击验证码重试。");
});
}
const captchaImg = document.getElementById("captcha-img");
if (captchaImg) {
// 允许用户点击验证码重新获取,避免因为一次请求失败而卡死
captchaImg.addEventListener("click", getCaptcha);
}
getCaptcha();
Original comment in English

suggestion (bug_risk): Captcha loading has no error handling, which can degrade the login experience.

If the captcha request fails (network/server issue), the image stays blank and the user can’t proceed or recover. Add error handling (e.g. a .catch(...) to display an error and/or trigger a retry) and consider regenerating the uuid so the form isn’t stuck on a failed captcha.

Suggested change
function getCaptcha() {
const uuid = getUuid()
document.getElementById("uuid").value = uuid
axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
document.getElementById("captcha-img").src = res.data.data
})
}
getCaptcha()
function getCaptcha() {
const uuid = getUuid();
const uuidInput = document.getElementById("uuid");
const captchaImg = document.getElementById("captcha-img");
// 如果关键元素不存在,直接返回避免报错
if (!uuidInput || !captchaImg) {
console.error("Captcha elements not found on the page.");
return;
}
uuidInput.value = uuid;
captchaImg.alt = "验证码加载中...";
axios
.get("v1/authorization-code/captchas/" + uuid)
.then(res => {
captchaImg.src = res.data.data;
captchaImg.alt = "看不清?点击刷新验证码";
})
.catch(err => {
console.error("Failed to load captcha.", err);
// 清空图片,避免展示旧的或损坏的图片
captchaImg.removeAttribute("src");
captchaImg.alt = "验证码加载失败,点击重试";
// 简单用户提示;如果项目有全局消息组件,可替换为全局提示
alert("验证码加载失败,请检查网络后点击验证码重试。");
});
}
const captchaImg = document.getElementById("captcha-img");
if (captchaImg) {
// 允许用户点击验证码重新获取,避免因为一次请求失败而卡死
captchaImg.addEventListener("click", getCaptcha);
}
getCaptcha();

Comment on lines +77 to +81
protected String getUrl(MinioClient minioClient) throws MinioException {
GetPresignedObjectUrlArgs objectUrlArgs = GetPresignedObjectUrlArgs.builder()
.bucket(this.minIO.getBucketName())
.object(fileInfo.name())
.method(Method.GET)
.method(Http.Method.GET)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 在 MinIO 的 GetPresignedObjectUrlArgs 中使用 Http.Method.GET 看起来前后不一致,并且可能无法通过编译。

之前这里使用的是 MinIO 的 io.minio.http.Method.GET,现在改成向 .method(...) 传入 Http.Method.GET。除非 Http.Methodio.minio.http.Method 是同一种类型,否则这段代码要么无法编译,要么会被 builder 拒绝。请继续使用 MinIO 的 Method 枚举,或者添加一个从 Http.Method 转换为 GetPresignedObjectUrlArgs.builder().method(...) 所需类型的显式转换。

Original comment in English

issue (bug_risk): Using Http.Method.GET with MinIO’s GetPresignedObjectUrlArgs looks inconsistent and may not compile.

This previously used MinIO’s io.minio.http.Method.GET, but now passes Http.Method.GET into .method(...). Unless Http.Method is the same type as io.minio.http.Method, this will fail to compile or be rejected by the builder. Please either keep using MinIO’s Method enum or add an explicit conversion from Http.Method to the type expected by GetPresignedObjectUrlArgs.builder().method(...).

- /doc.html=laokou-gateway
- /webjars/**=laokou-gateway
- /ws=laokou-gateway
- /api/login=laokou-gateway

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Login blocked by gateway 🐞 Bug ✓ Correctness

网关移除了 /api/login 的放行规则后,AuthFilter 会对未带 Authorization 的登录页请求直接返回 401,导致授权码登录页不可访问。由于 auth 服务
context-path 为 /api 且 LoginController 映射 /login,登录页实际路径为 /api/login。
Agent Prompt
### Issue description
Gateway 的 `request-matcher.ignore-patterns.GET` 中移除了 `/api/login`,而 `AuthFilter` 对未命中放行列表且缺少 `Authorization` 的请求会直接返回 401,导致登录页(`/api/login`)无法访问。

### Issue Context
- auth 服务 `server.servlet.context-path=/api`,`GET /login` 实际对外为 `/api/login`。
- 登录页还会加载静态资源(例如 `/api/js/**`, `/api/img/**`),如通过网关访问也应同步放行。

### Fix Focus Areas
- laokou-cloud/laokou-gateway/src/main/resources/application.yml[190-207]
- laokou-cloud/laokou-gateway/src/main/java/org/laokou/gateway/filter/AuthFilter.java[64-86]
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/application.yml[30-55]
- laokou-service/laokou-auth/laokou-auth-adapter/src/main/java/org/laokou/auth/web/LoginController.java[24-38]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +108 to 121
<input id="uuid" name="uuid" type="text" autocomplete="new-password" hidden="hidden" placeholder="请输入唯一标识" required/>
</div>

<div class="form-item row" style="width: 100%;">
<input id="username" name="username" type="text" placeholder="请输入用户名" required/>
<input id="tenant_code" name="tenant_code" autocomplete="new-password" value="laokouyun" type="text" placeholder="请输入租户编号" required autofocus/>
</div>

<div class="form-item row" style="width: 100%;">
<input id="password" name="password" type="password" placeholder="请输入密码" required/>
<input id="username" name="username" type="text" autocomplete="new-password" value="admin" placeholder="请输入用户名" required/>
</div>

<div class="form-item row" style="width: 100%;">
<input id="password" name="password" type="password" autocomplete="new-password" value="admin123" placeholder="请输入密码" required/>
</div>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Hardcoded admin credentials 🐞 Bug ⛨ Security

两个 login.html 模板将 tenant_code/username/password 预填为
laokouyun/admin/admin123,任何未认证访问者都能直接看到并一键尝试该组合,存在明显账号安全风险。
Agent Prompt
### Issue description
登录页模板硬编码并预填了 `tenant_code` / `username` / `password`(`laokouyun` / `admin` / `admin123`)。这会把“默认凭据”暴露给所有访问者,并显著降低账号安全性。

### Issue Context
这是服务端渲染模板(Thymeleaf),任何未认证访问者都可查看页面源代码或直接看到输入框中的默认值。

### Fix Focus Areas
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[111-121]
- laokou-service/laokou-standalone/laokou-standalone-auth/laokou-standalone-auth-start/src/main/resources/templates/login.html[111-121]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 123 to +152
<div class="form-item">
<div class="row">
<input id="captcha" name="captcha" type="text" placeholder="请输入验证码" required/>
<img class="captcha" th:src="@{/captcha}" alt="captcha"
onclick="this.src='/captcha?ts='+Date.now()"/>
<input id="captcha" name="captcha" autocomplete="new-password" type="text" placeholder="请输入验证码" required/>
<img id="captcha-img" class="captcha" alt="验证码" onclick="getCaptcha()"/>
</div>
</div>

<button class="btn" type="submit">登&nbsp;&nbsp;录</button>
</form>
</div>
<script>
function getUuid() {
if (window.crypto && crypto.randomUUID) {
return crypto.randomUUID();
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getCaptcha() {
const uuid = getUuid()
document.getElementById("uuid").value = uuid
axios.get("v1/authorization-code/captchas/" + uuid).then(res => {
document.getElementById("captcha-img").src = res.data.data
})
}
getCaptcha()
</script>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Captcha not validated server-side 🐞 Bug ⛨ Security

登录页强制填写 uuid/captcha 并从 /v1/authorization-code/captchas/{uuid} 获取验证码,但当前 formLogin 认证链路使用默认
DaoAuthenticationProvider,未看到对 uuid/captcha 的服务端校验,验证码形同虚设且可被直接绕过。
Agent Prompt
### Issue description
登录页引入了 `uuid`/`captcha` 并要求用户填写,但当前 Spring Security 的 formLogin 认证链路未实现对这些参数的服务端校验,导致验证码只存在于前端交互层面,攻击者可直接 POST `/login` 绕过。

### Issue Context
- GET `/v1/authorization-code/captchas/{uuid}` 会生成验证码并写入 Redis(key 由控制器使用 `RedisKeyUtils.getAuthorizationCodeAuthCaptchaKey(uuid)` 生成),并返回 base64 图片。
- 但 formLogin 使用默认认证流程(DaoAuthenticationProvider),默认只校验 username/password。

### Fix Focus Areas
- laokou-service/laokou-auth/laokou-auth-start/src/main/resources/templates/login.html[107-152]
- laokou-service/laokou-auth/laokou-auth-app/src/main/java/org/laokou/auth/command/query/CaptchaGetQryExe.java[40-51]
- laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2ResourceServerConfig.java[49-72]
- laokou-service/laokou-auth/laokou-auth-infrastructure/src/main/java/org/laokou/auth/config/OAuth2AuthorizationServerConfig.java[176-186]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
67.6% Duplication on New Code (required ≤ 3%)
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant